package com.hongwang.filter;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
import com.hongwang.annotations.Idempotency;
import com.hongwang.request.AbstractIdempotenceRequest;
import com.hongwang.utils.RedisTemplateUtils;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author 1
 * @date 2018/1/15
 */
@Activate(group = Constants.PROVIDER)
public class IdempotenceFilter implements Filter {

    Logger logger = LoggerFactory.getLogger(IdempotenceFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long start = System.currentTimeMillis();

        //类
        Class<?> cls = invoker.getInterface();
        //方法
        String methodName = invocation.getMethodName();
        //参数
        Class<?>[] parameterTypes = invocation.getParameterTypes();
        //参数value
        Object[] values = invocation.getArguments();
        Object request = null;
        RpcContext context = RpcContext.getContext();

        if (Objects.nonNull(parameterTypes) && Objects.nonNull(values)) {
            Method method = null;
            try {
                method = cls.getMethod(methodName, parameterTypes);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            Idempotency idempotency = (Idempotency) method.getAnnotation(Idempotency.class);
            if (Objects.nonNull(idempotency)) {
                if (values[0] instanceof AbstractIdempotenceRequest) {
                    request = ((AbstractIdempotenceRequest) values[0]);
                }
                StringBuffer rdsKeyStr = new StringBuffer("idempotency:" + cls.getPackage() + ":" + cls.getSimpleName() + ":" + methodName + ":");
                rdsKeyStr.append(((AbstractIdempotenceRequest)request).getToken());
                if(RedisTemplateUtils.check(rdsKeyStr.toString())){
                    return new RpcResult(new RuntimeException("幂等性错误!!!"));
                }else{
                    RedisTemplateUtils.set(rdsKeyStr.toString(),((AbstractIdempotenceRequest)request).getToken(),1, TimeUnit.MINUTES);
                }
            }
        }

        Result result = invoker.invoke(invocation);
        long elapsed = System.currentTimeMillis() - start;
        if (invoker.getUrl() != null) {
            logger.info("[{}], [{}], {}, [{}], [{}], [{}]   ", invoker.getInterface(), invocation.getMethodName(),
                    Arrays.toString(invocation.getArguments()), result.getValue(),
                    result.getException(), elapsed);

        }
        return result;
    }
}
